home *** CD-ROM | disk | FTP | other *** search
- /*
- AtExitToShell.c
-
- void YourFunction(void);
-
- error=AtExitToShell(YourFunction);
-
- AtExitToShell(YourFunction) requests that your function be called when the
- application quits, i.e. calls the ExitToShell trap, which tells the MacOS that
- it's done. Your function must have no arguments and no return value.
-
- Many VideoToolbox routines set up interrupt service routines that must be killed
- before the program goes away. We want to kill these whether we quit via exit(),
- abort(), or the ExitToShell trap is invoked directly, e.g. if user types "ES"
- in MacsBug. The only way to be sure of killing something before the application
- goes away is to attach its killer, by patching, to the ExitToShell trap. That's
- what's done here.
-
- AtExitToShell() is closely modeled on the ANSI function atexit(). I wrote it to
- overcome the restrictive implementation of atexit() and _atexit() in CodeWarrior:
- they only invoke your functions if the ANSI function exit() is called, NOT if
- you call abort(), or the user types "ES" in MacsBug. I think that AtExitToShell
- is equivalent to the non-ANSI _atexit() routine provided by the Symantec THINK C
- environment.
-
- The registration list (of user functions) is last-in, first-out. When you
- eventually quit, your functions will be called in reverse of the order in which
- you registered them. No checking is made for duplication: the same function may
- be registed multiple times, and will be called multiple times.
-
- CAUTION: your application's runtime environment will normally have shut itself
- down by the time it calls ExitToShell(), so a function scheduled for that time
- should not assume the availability of such services (e.g. printf). There's no
- restriction on the use of MacOS services.
-
- CAUTION: the atexit() and _atexit() routines should not be used in MATLAB code
- resources. Your function would only be invoked when MATLAB quits, after your code
- resources have already been flushed, so you'll crash. Conditionals below make
- AtExitToShell() innocuous if MATLAB is true, making this routine do nothing.
- However, it ought to be fairly easy to get MATLAB to call MyExitToShell() just
- before it disposes of our MEX resource, in which case all the existing calls to
- AtExitToShell() would then do the right thing.
-
- The code to patch ExitToShell is based on examples that appeared in UseNet
- csmp-digest-v3-046 by Kevin Bell (kbell@cs.utexas.edu) and Bill Hofmann
- (wdh@netcom.com) in response to a query by Steve Coy (stevec@jolt.mpx.com.au)
-
- HISTORY:
- 10/27/94 dgp wrote the ExitToShell patch, based on code from UseNet csmp-digest.
- 6/17/95 dgp wrote AtExitToShell.c
- 7/1/95 dgp made compatible with pre-universal apple headers.
- Disable if MATLAB is true. Added comments about MATLAB.
- 7/17/95 dgp made compatible with pre-universal headers
- */
- #include "VideoToolbox.h"
- #ifndef __TRAPS__
- #include <Traps.h> // _ExitToShell
- #endif
- #include <SegLoad.h> // ExitToShell()
- #if UNIVERSAL_HEADERS
- typedef UniversalProcPtr TrapAddressType;
- #else
- #define UniversalProcPtr ProcPtr
- #define NewRoutineDescriptor(a,b,c) a
- typedef long TrapAddressType;
- #endif
- static pascal void MyExitToShell(void);
- #define FUNCTIONS 35
- static UniversalProcPtr oldExitToShellTrapAddress=NULL;
- static void (*userFunction[FUNCTIONS])(void);
-
- int AtExitToShell(void (*userFunctionPtr)(void))
- {
- UniversalProcPtr myExitToShellUPP;
- int i;
-
- if(oldExitToShellTrapAddress==NULL){
- #if !MATLAB
- myExitToShellUPP=NewRoutineDescriptor((ProcPtr)MyExitToShell
- ,kPascalStackBased,GetCurrentISA());
- oldExitToShellTrapAddress=(UniversalProcPtr)GetToolTrapAddress(_ExitToShell);
- SetToolTrapAddress((TrapAddressType)myExitToShellUPP,_ExitToShell);
- #else
- // Someday we should put code here that asks MATLAB to call MyExitToShell
- // just before disposing of our MEX resource.
- #endif
- for(i=0;i<FUNCTIONS;i++)userFunction[i]=NULL;
- }
- for(i=0;i<FUNCTIONS;i++)if(userFunction[i]==NULL){
- userFunction[i]=userFunctionPtr;
- return 0; // success
- }
- return 1; // failure
- }
-
- static pascal void MyExitToShell(void)
- {
- int i;
-
- SetCurrentA5();
- #if !MATLAB
- SetToolTrapAddress((TrapAddressType)oldExitToShellTrapAddress,_ExitToShell);
- #endif
- for(i=FUNCTIONS-1;i>=0;i--)if(userFunction[i]!=NULL){
- (*userFunction[i])();
- }
- #if !MATLAB
- ExitToShell();
- #endif
- }
-